use std::{
    future::Future,
    pin::Pin,
    sync::{Arc, Mutex},
    task::{Context, Poll, Waker},
    thread,
    time::Duration,
};

// 实现Future定时器
// 定时器创建时，我们会启动一个线程，接着让该线程进入睡眠，睡眠结束后再通知给Future
pub struct TimerFuture {
    // 由于是多线程环境，所以我们使用 Arc<Mutex<T>> 进行共享某个变量T
    // 此处T使用 struct SharedState 
    shared_state: Arc<Mutex<SharedState>>
}

// 用于在Future和等待的线程 之间共享状态的变量类型
struct SharedState {
    completed: bool, // 定时睡眠是否结束
    waker: Option<Waker>, // 当睡眠结束后，线程可以用 `waker` 通知 `TimerFuture` 来唤醒任务
}

// 为TimerFuture实现Future
impl Future for TimerFuture {
    type Output = ();

    fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
        // 通过检查共享状态，来去欸的那个定时器是否已经完成
        // shared_state 是一个Mutex互斥量，通过lock可以在锁定数据变量的同时，得到被MutexGuard智能指针包裹的数据变量
        let mut shared_state = self.shared_state.lock().unwrap();
        
        // shared_state 使用的话可以自动解引用
        if shared_state.completed {
            // 已经完成了，那就告诉调用方当前Future Ready 了
            Poll::Ready(())
        } else {
            // 计时器没有计时完毕，我们设置 waker,
            // 这样的话，新线程在睡眠计时结束后可以唤醒当前的任务，接着再次堆Future进行Poll，
            // ---
            // 此处之所以每一次调用都将 context 中的waker拷贝给共享状态的waker是怕被其他的任务篡改
            // 其他的任务？
            shared_state.waker = Some(cx.waker().clone());
            Poll::Pending
        }
    }

}

impl TimerFuture {
    
    // 创建一个新的 TimerFuture 在指定的时间结束后，该Future会完成
    pub fn new(duration: Duration) -> Self {
        let shared_state = Arc::new(Mutex::new(SharedState{
            completed: false,
            waker: None,
        }));

        // 创建一个新的线程
        // 克隆一个互斥量的引用，以便在线程中使用
        let thread_shared_state = shared_state.clone();
        thread::spawn(move||{
            thread::sleep(duration); // 睡眠指定的时间，实现计时功能
            let mut shared_state = thread_shared_state.lock().unwrap();
            // 睡完了之后，通知执行器定时器结束了，可以继续 poll 对应的 Future 了
            shared_state.completed = true;
            if let Some(waker) = shared_state.waker.take() {
                waker.wake() // 唤醒，但是还不知道这个是啥意思!?
            }
        });

        TimerFuture { shared_state: shared_state }
    }
}

